<?php
// 应用公共文件

/**
 * 请求返回结果--用于api
 * @param int $status 1:true,0:false
 * @param int $code
 * @param string $msg
 * @param array $data
 * @return json
 */
function _result($status = 0, $data = [], $code = 1001, $msg = '')
{
  $result['status'] = $status == 1 ? 1 : $status;
  $result['code'] = $code;
  if ($msg == '') {
    $result['msg'] = isset(config('error')[$code]) ? config('error')[$code] : '';
  } else {
    $result['msg'] = $msg;
  }
  $result['data'] = $data;
  $result['time'] = time(); // 请求返回时间
  return json($result);
}


/**
 * 正确输出
 * @return json
 */
function _jok($msg = '', $data = [], $code = 0, $httpStatus = 200)
{
  $result = _ok($msg,$data,$code);
  return json($result,$httpStatus);
}

/**
 * 错误输出
 * @return json 
 */
function _jerr($msg = '', $data = [], $code = -2, $httpStatus = 200)
{
  $result = _err($msg,$data,$code);
  return json($result,$httpStatus);
}

/**
 * 正确输出
 * @return array  $code可以为大于0的参数 0就不用写
 */
function _ok($msg = '', $data = [], $code = 0)
{
  if(isset($msg) && !empty($msg) && is_numeric($msg)){
    $result = ['status' => true, 'msg' => (isset(config('error')[$msg]) ? config('error')[$msg] : $msg), 'data' => $data, 'code' => $code];
  }else{
    $result = ['status' => true, 'msg' => $msg, 'data' => $data, 'code' => $code];
  }
  return $result;
}

/**
 * 错误输出
 * @return array
 */
function _err($msg = '', $data = [], $code = -2)
{
  if(isset($msg) && !empty($msg) && is_numeric($msg)){
    $result = ['status' => false, 'msg' => (isset(config('error')[$msg]) ? config('error')[$msg] : $msg), 'data' => $data, 'code' => $code];
  }else{
    $result = ['status' => false, 'msg' => $msg, 'data' => $data, 'code' => $code];
  }
  return $result;
}

/**
 * Layui 数据输出
 */
function _layui($count = 1, $data = [], $msg = 'OK')
{
  if ($count === 0 || empty($data)) {
    return array("code" => 1, "msg" => '暂无数据', "count" => 0, "data" => []);
  }
  return array('code' => 0, 'msg' => $msg, 'count' => $count, 'data' => $data);
}

/**
 * 获取客户端IP地址
 * @param int $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
 * @param bool $adv 是否进行高级模式获取（有可能被伪装）
 * @return mixed
 */
function _gip($type = 0, $adv = false)
{
  $type =  $type ? 1 : 0;
  static $ip  =   NULL;
  if ($ip !== NULL) return $ip[$type];
  if ($adv) {
    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
      $arr    =   explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
      $pos    =   array_search('unknown', $arr);
      if (false !== $pos) unset($arr[$pos]);
      $ip     =   trim($arr[0]);
    } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
      $ip     =   $_SERVER['HTTP_CLIENT_IP'];
    } elseif (isset($_SERVER['REMOTE_ADDR'])) {
      $ip     =   $_SERVER['REMOTE_ADDR'];
    }
  } elseif (isset($_SERVER['REMOTE_ADDR'])) {
    $ip = $_SERVER['REMOTE_ADDR'];
  }
  // IP地址合法验证
  $long = sprintf("%u", ip2long($ip));
  $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
  return $ip[$type];
}

/**
 * 获取/配置系统参数
 * @param string $name 参数名称
 * @param string $value 默认是null为获取值，否则为更新
 * @return string|bool
 */
function _conf($name, $value = null)
{
  $conf = new \app\common\service\sys\ConfigService();
  return $conf->sysconf($name, $value);
}

/**
 * 返回图片地址
 * @param string $file_id
 * @return array|mixed|string
 */
function _img($file_id = '')
{
  return (new \app\common\service\sys\FilesService())->getFilesUrl($file_id);
}

/**
 * 文件使用次数变更
 * @param string $file_id
 * @param string $num
 * @return array|mixed|string
 */
function _use_file($file_id = '', $num)
{
  return (new \app\common\service\sys\FilesService())->useCount($file_id, $num);
}

/**
 * 时间字符串转时间戳
 * @param string $key
 * @param array $data
 * @return int|null
 */
function str2time($key, $data)
{
  if (isset($data[$key]) && !empty($data[$key])) {
    return strtotime($data[$key]);
  }
  return null;
}

/**
 * 时间戳转Y-m-d H:i:s
 * @param int $time
 * @return string
 */
function time2str($time = 0, $type = 1)
{
  if (is_numeric($time) && $type === 1) {
    return date('Y-m-d H:i:s', $time);
  } elseif (is_numeric($time) && $type === 2) {
    return date('Y-m-d', $time);
  }
  return '';
}

/**
 * 处理check值为on
 * @param string $key
 * @param array $data
 * @return int 1|2
 */
function checkon($key, $data)
{
  if (isset($data[$key])) {
    if ($data[$key] == 'on' || $data[$key] == '1' || $data[$key] == 1) {
      return 1;
    }
  }
  return 2;
}

/**
 * 前端日期范围转where条件
 * 数据表时间字段为 createtime
 * @param string $key
 * @param array $post
 * @param array $where
 * @return void
 */
function date2where($key, $post, &$where)
{
  if (isset($post[$key]) && !empty($post[$key])) {
    $date_string = $post[$key];
    $date_array = explode('到', urldecode($date_string));
    $stime = strtotime($date_array[0] . '00:00:00');
    $etime = strtotime($date_array[1] . '23:59:59');
    $where[] = ['createtime', 'between', [$stime, $etime]];
  }
}

/**
 * JSON(对象)转数组
 */
function object_array($data)
{
  if (is_object($data)) {
    $data =  json_decode(json_encode($data), true);
  }
  return $data;
}

/**
 * 生成令牌(注意需要开启session)
 * @param string $form 表单
 * @param bool $isdd 是否输出input 
 * @return string | array
 */
function kaigeToken($form = 'form', $isdd = false)
{
  $key = $form . '_token_';
  $data = token('__Kaige_Token__', 'sha1');
  cache($key, $data, 7200);   //2小时过期
  if ($isdd) {
    return ['form' => $form, 'data' => $data];
  }
  return '<input type="hidden" name="validate_form" value="' . $form . '"><input type="hidden" name="__Kaige_Token__" value="' . $data . '" class="Kaige_Token">';
}


/***
 * 令牌校检
 * @return array
 */
function validatekaigeToken()
{
  $_token      = input('__Kaige_Token__/s', '');
  $form        = input('validate_form/s', '');
  $key = $form . '_token_';
  $cache_token = cache($key);

  if (!$_token || $_token != $cache_token) {
    if (request()->isAjax()) {

      $new_token = token('__Kaige_Token__', 'sha1');
      cache($key, $new_token, 7200);   //2小时过期
      $return = [
        'data'   => '',
        'msg'    => '已超时或重复提交，请重试或刷新页面',
        'status' => false,
        'token'  => $new_token
      ];
      header('Content-type:text/json');
      echo json_encode($return);
      exit;
    } else {
      die("Stop. Thank You!");
    }
  }
}

/**
 * 返回当前的毫秒时间戳
 * @return string
 */
function msectime()
{
  list($tmp1, $tmp2) = explode(' ', microtime());
  return sprintf('%.0f', (floatval($tmp1) + floatval($tmp2)) * 1000);
}

/**
 * 驼峰转下划线规则
 * @param string $node
 * @return string
 */
function parseNodeStr($node)
{
  $tmp = [];
  foreach (explode('/', $node) as $name) {
    $tmp[] = strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
  }
  $tmp = str_replace("._",".",$tmp); //多级控制器，须过滤一下
  return trim(join('/', $tmp), '/');
}

/**
 * GUID唯一标识符
 */
function create_guid()
{
  $charid = strtoupper(md5(uniqid(mt_rand(), true)));
  $hyphen = chr(45);
  $uuid = substr($charid, 0, 8) . $hyphen . substr($charid, 8, 4) . $hyphen . substr($charid, 12, 4) . $hyphen . substr($charid, 16, 4) . $hyphen . substr($charid, 20, 12);
  return $uuid;
}

/**
 * 自动生成ID
 */
function autoid()
{
  return \app\common\util\IdWork::getInstance()->setWorkId(\think\facade\Config::get('kaige.idworkid', 1))->nextId();
}

function getBrowser()
{
  $user_OSagent = $_SERVER['HTTP_USER_AGENT'];
  if (strpos($user_OSagent, "Maxthon") && strpos($user_OSagent, "MSIE")) {
    $visitor_browser = "Maxthon(Microsoft IE)";
  } elseif (strpos($user_OSagent, "Maxthon 2.0")) {
    $visitor_browser = "Maxthon 2.0";
  } elseif (strpos($user_OSagent, "Maxthon")) {
    $visitor_browser = "Maxthon";
  } elseif (strpos($user_OSagent, "Edge")) {
    $visitor_browser = "Edge";
  } elseif (strpos($user_OSagent, "Trident")) {
    $visitor_browser = "IE";
  } elseif (strpos($user_OSagent, "MSIE")) {
    $visitor_browser = "IE";
  } elseif (strpos($user_OSagent, "MSIE")) {
    $visitor_browser = "MSIE";
  } elseif (strpos($user_OSagent, "NetCaptor")) {
    $visitor_browser = "NetCaptor";
  } elseif (strpos($user_OSagent, "Netscape")) {
    $visitor_browser = "Netscape";
  } elseif (strpos($user_OSagent, "Chrome")) {
    $visitor_browser = "Chrome";
  } elseif (strpos($user_OSagent, "Lynx")) {
    $visitor_browser = "Lynx";
  } elseif (strpos($user_OSagent, "Opera")) {
    $visitor_browser = "Opera";
  } elseif (strpos($user_OSagent, "MicroMessenger")) {
    $visitor_browser = "WeiXinBrowser";
  } elseif (strpos($user_OSagent, "Konqueror")) {
    $visitor_browser = "Konqueror";
  } elseif (strpos($user_OSagent, "Mozilla/5.0")) {
    $visitor_browser = "Mozilla";
  } elseif (strpos($user_OSagent, "Firefox")) {
    $visitor_browser = "Firefox";
  } elseif (strpos($user_OSagent, "U")) {
    $visitor_browser = "Firefox";
  } else {
    $visitor_browser = "Other Browser";
  }
  return $visitor_browser;
}

function getOS()
{
  $OS = $_SERVER['HTTP_USER_AGENT'];
  if (preg_match('/win/i', $OS)) {
    $OS = 'Windows';
  } elseif (preg_match('/mac/i', $OS)) {
    $OS = 'MAC';
  } elseif (preg_match('/linux/i', $OS)) {
    $OS = 'Linux';
  } elseif (preg_match('/unix/i', $OS)) {
    $OS = 'Unix';
  } elseif (preg_match('/bsd/i', $OS)) {
    $OS = 'BSD';
  } else {
    $OS = 'Other';
  }
  return $OS;
}

function files_self($type = '')
{
  $result = '';
  switch ($type) {
    case 'ext':
      $result = str_replace(',', '|', config('kaige.file_ext'));
      break;
    case 'mime':
      $result = config('kaige.file_mime');
      break;
  }
  return $result;
}

/**
 * 文件大小单位格式化
 * @param $size
 * @return string
 */
function files_size_format($size)
{
  $size_name = array("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB");
  return round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . $size_name[$i];
}


/**
 * 系统加密方法
 * @param string $data 要加密的字符串
 * @param string $key 加密密钥
 * @param int $expire 过期时间 单位 秒
 * @return string
 */
function think_encrypt($data, $key = '', $expire = 0)
{
  $key  = md5(empty($key) ? config('kaige.pass_salt') : $key);
  $data = base64_encode($data);
  $x    = 0;
  $len  = strlen($data);
  $l    = strlen($key);
  $char = '';

  for ($i = 0; $i < $len; $i++) {
    if ($x == $l) $x = 0;
    $char .= substr($key, $x, 1);
    $x++;
  }

  $str = sprintf('%010d', $expire ? $expire + time() : 0);

  for ($i = 0; $i < $len; $i++) {
    $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1))) % 256);
  }

  $str = str_replace(array('+', '/', '='), array('-', '_', ''), base64_encode($str));
  return strtoupper(md5($str)) . $str;
}

/**
 * 系统解密方法
 * @param  string $data 要解密的字符串 （必须是think_encrypt方法加密的字符串）
 * @param  string $key 加密密钥
 * @return string
 */
function think_decrypt($data, $key = '')
{
  $key  = md5(empty($key) ? config('kaige.pass_salt') : $key);
  $data = substr($data, 32);
  $data = str_replace(array('-', '_'), array('+', '/'), $data);
  $mod4 = strlen($data) % 4;
  if ($mod4) {
    $data .= substr('====', $mod4);
  }
  $data   = base64_decode($data);
  $expire = substr($data, 0, 10);
  $data   = substr($data, 10);

  if ($expire > 0 && $expire < time()) {
    return '';
  }
  $x    = 0;
  $len  = strlen($data);
  $l    = strlen($key);
  $char = $str = '';

  for ($i = 0; $i < $len; $i++) {
    if ($x == $l) $x = 0;
    $char .= substr($key, $x, 1);
    $x++;
  }

  for ($i = 0; $i < $len; $i++) {
    if (ord(substr($data, $i, 1)) < ord(substr($char, $i, 1))) {
      $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
    } else {
      $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
    }
  }
  return base64_decode($str);
}

/**
 * 用户密码加密方法，虑盐值+创建时间
 * @param string $pass 原始密码
 * @return string 多重加密后的32位小写MD5码
 */
function encrypt_pass($pass, $salt, $ctime = 0)
{
  if ('' == $pass) {
    return '';
  }
  $pass = trim($pass);
  $salt = trim($salt);
  return md5(sha1($pass) . $salt . $ctime);
}

/**
 * 加密方法
 * @param string $str
 * @return string
 */
function k_encrypt($str, $screct_key = '')
{
  $key = config('kaige.pass_salt');
  $screct_key = $screct_key ? $screct_key : $key;
  //AES, 128 模式加密数据 CBC
  $iv = substr($screct_key, 0, 16);
  $str = trim($str);
  $str = addPKCS7Padding($str);
  $encrypt_str = openssl_encrypt($str, 'aes-128-cbc', $screct_key, OPENSSL_RAW_DATA, $iv);
  return base64_encode($encrypt_str);
}

/**
 * 解密方法
 * @param string $str
 * @return string
 */
function k_decrypt($str, $screct_key = '')
{
  $key = config('kaige.pass_salt');
  $screct_key = $screct_key ? $screct_key : $key;
  //AES, 128 模式加密数据 CBC
  $iv = substr($screct_key, 0, 16);
  $str = base64_decode($str);
  $decrypt_str = openssl_decrypt($str, 'aes-128-cbc', $screct_key, OPENSSL_RAW_DATA, $iv);
  $decrypt_str = trim($decrypt_str);
  $decrypt_str = stripPKSC7Padding($decrypt_str);
  return $decrypt_str;
}

/**
 * 填充算法
 * @param string $source
 * @return string
 */
function addPKCS7Padding($source, $block = 16)
{
  $source = trim($source);
  $pad = $block - (strlen($source) % $block);
  if ($pad <= $block) {
    $char = chr($pad);
    $source .= str_repeat($char, $pad);
  }
  return $source;
}
/**
 * 移去填充算法
 * @param string $source
 * @return string
 */
function stripPKSC7Padding($source)
{
  $source = trim($source);
  $char = substr($source, -1);
  $num = ord($char);
  if ($num == 62) return $source;
  $source = substr($source, 0, -$num);
  return $source;
}

/**
 * 数组转对象
 * @param Array $array
 * @return Object
 */
function array2Object(array $array)
{
  if (is_array($array)) {
    $obj = new class
    {
    };
    foreach ($array as $key => $val) {
      $obj->$key = $val;
    }
  } else {
    $obj = $array;
  }
  return $obj;
}


/**
 * xml转数组
 * @param $xml
 * @return mixed
 */
function xmlToArray($xml)
{
    libxml_disable_entity_loader(true);
    $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    return $values;
}

/**
 * 对前端传值有encodeURIComponent编码的进行解码 同样仅到2维数组
 */
function rq_decode($data){
  if(isset($data) && empty($data)) return $data;
  if(is_array($data)){
    foreach($data as $key=>$val){ //第一层
      if(is_string($val)){
        $data[$key] = urldecode($val);
      }elseif(is_array($val)){
        foreach($val as $key2=>$val2){ //第二层
          if(is_string($val2)){
            ($data[$key])[$key2] = urldecode($val2);
          }
        }
      }
    }
  }
  return $data;
}
/**
 * 解析根据分组、部门选择的结果
 */
function parse_ugdc($data)
{
  return (new \app\common\service\sys\UserGroupService())->parseUgdc($data);
}

/**
 * 生成编号
 * @param $type 类别
 * @param $q 前缀
 * @return string
 */
function get_sn($type,$q)
{
    switch ($type) {
        case 1: //流程编号
            $str = $q . date('ymdHis') . mt_rand(1000, 9999);
            break;
        case 2: 
            $str = $q . substr(msectime() . rand(0, 9), 1);
            break;
        default:
            $str = substr(msectime() . rand(0, 9), 1);
    }
    return $str;
}
